#include "StdAfx.h"
#include "lua/luaHelp.h"

NAMESPACE_LUA_BEGIN
LUA_EXTERN_C TValue *index2adr (lua_State *L, int idx);
LUA_EXTERN_C Table *getcurrenv (lua_State *L);
NAMESPACE_LUA_END

USING_NAMESPACE_LUA

using namespace luaHelp;

#undef api_check
#define api_check(L, o)		luaplus_assert(o)

#if !LUA_REFCOUNT
#define setnilvalue2n(L,obj) setnilvalue((obj))
#define setbvalue2n(obj,x) setbvalue((obj),(x))
#define setclvalue2n(L,obj,x) setclvalue((L),(obj),(x))
#define sethvalue2n(L,obj,x) sethvalue((L),(obj),(x))
#define setnvalue2n(obj,x) setnvalue((obj),(x))
#define setpvalue2n(obj,x) setpvalue((obj),(x))
#define setuvalue2n(L,obj,x) setuvalue((L),(obj),(x))
#endif
//----------------------Lua Object---------------------

//----------------------Lua Table----------------------
LuaTable::LuaTable() :
m_state(NULL)
{
	setnilvalue2n(NULL, &m_object);
}


LuaTable::LuaTable(LuaState* state) throw():
m_state(state)
{
	//AddToUsedList(state);
	setnilvalue2n(m_state, &m_object);
}


LuaTable::LuaTable(LuaState* state, int stackIndex) throw():
m_state(state)
{
	luaplus_assert(lua_istable(state->GetCState(),stackIndex));
	m_object = *index2adr(state->GetCState(), stackIndex);
}


LuaTable::LuaTable(LuaState* state, const LuaObject& luaObj):
m_state(state)
{
	luaplus_assert(ttype(&luaObj) == LUA_TTABLE);
	m_object = luaObj;
}

LuaTable::LuaTable(const LuaTable& src) throw()
{
	if (src.m_state)
	{
		m_state = src.m_state;
		m_object = src.m_object;
	}
	else
	{
		m_state = NULL;
		setnilvalue2n(m_state, &m_object);
	}
}

LuaTable& LuaTable::operator=(const LuaTable& src) throw()
{
	if (src.m_state)
	{
		m_state = src.m_state;
		m_object = src.m_object;
	}
	else
	{
		m_state = NULL;
		setnilvalue2n(m_state, &m_object);
	}
	return *this;
}
//Help function
void LuaTable::SetTableHelper(const char* key, LuaObject* valueObj)
{
	lua_State *L = m_state->GetCState();	(void)L;
	lua_TValue keyObj;
	setsvalue2n(L, &keyObj, luaS_newlstr(L, key, strlen(key)));
	luaV_settable(L, &m_object, &keyObj, valueObj);
	setnilvalue(&keyObj);
}


void LuaTable::SetTableHelper(int key, LuaObject* valueObj)
{
	lua_TValue keyObj;
	setnvalue2n(&keyObj, key);
	luaV_settable(m_state->GetCState(), &m_object, &keyObj, valueObj);
}


void LuaTable::SetTableHelper(const LuaObject* keyObj, const LuaObject* valueObj)
{
	luaV_settable(m_state->GetCState(), &m_object, (TValue*)keyObj, (TValue*)valueObj);
}


void LuaTable::SetTableHelper(const LuaObject& key, LuaObject* valueObj)
{
	luaV_settable(m_state->GetCState(), &m_object, (TValue*)&key, valueObj);
}



//Set 
void  LuaTable::SetNil(const char* key)
{
	lua_TValue valueObj;
	setnilvalue2n(m_state, &valueObj);
	return SetTableHelper(key, &valueObj);
}
void  LuaTable::SetNil(int key)
{
	lua_TValue valueObj;
	setnilvalue2n(m_state, &valueObj);
	return SetTableHelper(key, &valueObj);
}
void  LuaTable::SetNil(LuaObject& key)
{
	lua_TValue valueObj;
	setnilvalue2n(m_state, &valueObj);
	return SetTableHelper(key, &valueObj);
}

//-------------------------------------------------------------
void		LuaState::InternalPushTObject(const LuaObject* tobject)
{
	lua_lock(m_state);
	setobj2s(m_state, m_state->top, tobject);
	api_incr_top(m_state);
	lua_unlock(m_state);
}
LuaTable	LuaState::CreateTable(const char* key, int narray/* = 0*/, int lnhash/* = 0*/)
{
	return LuaTable();
}
LuaTable	LuaState::CreateTable(int key, int narray/* = 0*/, int lnhash/* = 0*/)
{
	return LuaTable();
}
LuaTable	LuaState::CreateTable(LuaObject& key, int narray/* = 0*/, int lnhash/* = 0*/)
{
	return LuaTable();
}
LuaTable	LuaState::CreateTable(int narr/* = 0*/, int nrec/* = 0*/)
{
	lua_createtable(m_state,narr,nrec);
	return LuaTable(this, GetTop());
}

//-------------------------------------------------------------------
int		LuaState::GetTop()
{
	return lua_gettop(GetCState());
}

void	LuaState::SetTop(int index)
{
	lua_settop(GetCState(), index);
}
void	LuaState::PushVFString(const char* fmt, va_list argp)
{
	lua_lock(m_state);
	lua_pushvfstring(m_state,fmt,argp);
	lua_unlock(m_state);
}
void	LuaState::PushFString(const char* fmt, ...)
{
	va_list argp;
	lua_lock(m_state);
	luaC_checkGC(m_state);
	va_start(argp, fmt);
	lua_pushvfstring(m_state,fmt,argp);
	va_end(argp);
	lua_unlock(m_state);
}